#include "types.h"

// QEMU virt 机器的UART地址
#define UART_BASE 0x10000000
#define UART_REG(reg) ((volatile uint8*)(UART_BASE + reg))

// UART寄存器偏移
#define UART_RHR 0  // 接收保持寄存器
#define UART_THR 0  // 发送保持寄存器
#define UART_IER 1  // 中断使能寄存器
#define UART_FCR 2  // FIFO控制寄存器
#define UART_ISR 2  // 中断状态寄存器
#define UART_LCR 3  // 线控制寄存器
#define UART_MCR 4  // 调制解调器控制寄存器
#define UART_LSR 5  // 线状态寄存器
#define UART_MSR 6  // 调制解调器状态寄存器
#define UART_SPR 7  // 暂存寄存器

// LSR位定义
#define UART_LSR_RX_READY (1 << 0)   // 数据就绪
#define UART_LSR_TX_EMPTY (1 << 5)   // 发送器空
#define UART_LSR_TX_IDLE  (1 << 6)   // 发送器空闲

// 初始化UART
void uart_init(void) {
    // 禁用中断
    *UART_REG(UART_IER) = 0x00;
    
    // 设置波特率 (115200)
    *UART_REG(UART_LCR) = 0x80;  // 启用DLAB
    *UART_REG(UART_THR) = 0x01;  // 分频低字节
    *UART_REG(UART_IER) = 0x00;  // 分频高字节
    
    // 8N1格式，禁用DLAB
    *UART_REG(UART_LCR) = 0x03;
    
    // 启用FIFO，清除它们，设置14字节阈值
    *UART_REG(UART_FCR) = 0xC7;
    
    // 启用中断
    *UART_REG(UART_IER) = 0x01;
}

// 检查是否可以发送字符
static int uart_can_send(void) {
    return *UART_REG(UART_LSR) & UART_LSR_TX_IDLE;
}

// 等待并发送一个字符
void uart_putc(char c) {
    // 等待发送器就绪
    while (!uart_can_send()) {
        // 忙等待
    }
    
    // 发送字符
    *UART_REG(UART_THR) = c;
    
    // 如果是换行，还需要发送回车
    if (c == '\n') {
        uart_putc('\r');
    }
}

// 批量发送字符串
void uart_puts(const char *str) {
    while (*str) {
        uart_putc(*str++);
    }
}

// 检查是否有数据可读
int uart_can_recv(void) {
    return *UART_REG(UART_LSR) & UART_LSR_RX_READY;
}

// 读取一个字符
char uart_getc(void) {
    while (!uart_can_recv()) {
        // 忙等待
    }
    return *UART_REG(UART_RHR);
}
/*
#define UART_BASE 0x10000000
#define LSR_THRE (1 << 5)   // 发送保持寄存器空标志

void uart_putc(char c) {
    volatile char *lsr = (volatile char *)(UART_BASE + 5);
    volatile char *thr = (volatile char *)UART_BASE;
    while ((*lsr & LSR_THRE) == 0); // 等待发送缓冲区空闲
    *thr = c;               // 写入字符
}*/

